import { router } from "@/router";
import { getInitTabs } from "@/router/routes/helpers";
import { zError } from "@/utils/console";
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import type { RouteLocationNormalized } from "vue-router";

export interface ZTabItem {
  label: string;
  fullPath: string;
  rebirth?: boolean;
  iframeUrl?: string;
  name?: string | null;
  icon?: string;
  closable?: boolean;
}

export const TABS_STORE = "tabs";

export const useTabsStore = defineStore(TABS_STORE, () => {
  const tabs = ref<ZTabItem[]>(getInitTabs());

  /**
   * @deprecated
   */
  function addTab(tabItem: ZTabItem) {
    if (!tabs.value.some((tab) => tab.label === tabItem.label)) {
      tabs.value.push(tabItem);
    } else {
      zError("Duplicated label in tabs");
    }
  }

  function addTabByRoute(route: RouteLocationNormalized) {
    const {
      fullPath,
      name,
      meta: { title, icon, fixed, hideTab, rebirth, iframeUrl },
      query: { tabName },
    } = route;

    if (!hideTab && !tabs.value.some((tab) => tab.label === title)) {
      tabs.value.push({
        fullPath,
        label: tabName ? `${title}(${tabName})` : title,
        name: name as string,
        rebirth,
        iframeUrl,
        icon,
        closable: !fixed,
      });
    }
  }

  function removeTabByLabel(tabLabel: string) {
    const tabIndex = getTabIndex(tabLabel);
    if (tabIndex !== -1) {
      const tab = tabs.value[tabIndex];
      if (tab.closable) {
        tabs.value.splice(tabIndex, 1);
        if (tabLabel === activeTabLabel.value) {
          _setDefaultTab();
        }
      }
    }
  }

  function getTabByLabel(tabLabel: string) {
    return tabs.value.find((tab) => tab.label == tabLabel);
  }

  function getTabIndex(tabLabel: string) {
    return tabs.value.findIndex((tab) => tab.label == tabLabel);
  }

  const activeTabLabel = ref<string>("");

  function setActiveTab(label: string) {
    activeTabLabel.value = label;
  }

  const activeTab = computed(() => {
    return getTabByLabel(activeTabLabel.value);
  });

  const activeTabIndex = computed(() => {
    return getTabIndex(activeTabLabel.value);
  });

  function _setDefaultTab() {
    if (tabs.value.length >= 1) {
      activeTabLabel.value = tabs.value.slice(-1)[0].label;
      router.push(tabs.value[0].fullPath);
    } else {
      activeTabLabel.value = "";
    }
  }

  /* operations */

  function closeAll() {
    tabs.value = getInitTabs();
    _setDefaultTab();
  }

  function closeTheOne(tabLabel = activeTabLabel.value) {
    removeTabByLabel(tabLabel);
  }

  function closeOthers(tabLabel = activeTabLabel.value) {
    const tab = getTabByLabel(tabLabel);
    if (tab) {
      router.push(tab.fullPath);
    }

    tabs.value = tabs.value.filter(
      (tab) => !tab.closable || tab.label === tabLabel
    );
  }

  function closeRight(tabLabel = activeTabLabel.value) {
    const tabIndex = getTabIndex(tabLabel);
    const tab = getTabByLabel(tabLabel);
    if (
      tab?.fullPath &&
      tabIndex < activeTabIndex.value &&
      activeTab.value?.closable
    ) {
      router.push(tab?.fullPath);
    }

    tabs.value = tabs.value.filter(
      (tab, index) => !tab.closable || index <= tabIndex
    );
  }

  function closeLeft(tabLabel = activeTabLabel.value) {
    const tabIndex = getTabIndex(tabLabel);
    const tab = getTabByLabel(tabLabel);
    if (
      tab?.fullPath &&
      tabIndex > activeTabIndex.value &&
      activeTab.value?.closable
    ) {
      router.push(tab?.fullPath);
    }

    tabs.value = tabs.value.filter(
      (tab, index) => !tab.closable || index >= tabIndex
    );
  }

  return {
    tabs,
    size: computed(() => tabs.value.length),
    addTab,
    addTabByRoute,
    removeTabByLabel,
    getTabIndex,
    getTabByLabel,
    activeTab,
    activeTabLabel,
    setActiveTab,

    closeTheOne,
    closeAll,
    closeOthers,
    closeRight,
    closeLeft,
  };
});
